﻿namespace Fluent.Internal;

using System;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

/// <summary>
/// Helper class used to queue action for completion or items changes of <see cref="ItemContainerGenerator"/>
/// </summary>
internal class ItemContainerGeneratorAction
{
    /// <summary>
    /// Creates a new instance used to queue action for completion or items changes of <see cref="ItemContainerGenerator"/>
    /// </summary>
    /// <param name="generator">The <see cref="ItemContainerGenerator"/> to be used.</param>
    /// <param name="action">The <see cref="System.Action"/> that should be invoked.</param>
    public ItemContainerGeneratorAction(ItemContainerGenerator generator, Action action)
    {
        this.Generator = generator;
        this.Action = action;
    }

    /// <summary>
    /// Gets the <see cref="ItemContainerGenerator"/> to be used.
    /// </summary>
    public ItemContainerGenerator Generator { get; }

    /// <summary>
    /// Gets the <see cref="System.Action"/> that should be invoked.
    /// </summary>
    public Action Action { get; }

    /// <summary>
    /// Gets the current wait state. <c>true</c> in case <see cref="QueueAction"/> was called and we are waiting for the <see cref="Generator"/> to finish.
    /// </summary>
    public bool IsWaitingForGenerator { get; private set; }

    /// <summary>
    /// Queues <see cref="Action"/> for invocation.
    /// </summary>
    public void QueueAction()
    {
        if (this.Generator.Status != GeneratorStatus.ContainersGenerated)
        {
            if (this.IsWaitingForGenerator)
            {
                return;
            }

            this.IsWaitingForGenerator = true;
            this.Generator.StatusChanged += this.HandleItemContainerGenerator_StatusChanged;
            return;
        }

        this.IsWaitingForGenerator = false;
        this.Generator.StatusChanged -= this.HandleItemContainerGenerator_StatusChanged;

        this.Action();
    }

    private void HandleItemContainerGenerator_StatusChanged(object? sender, EventArgs e)
    {
        this.QueueAction();
    }
}